package com.cc.parking.common.config

import com.cc.common.interceptor.AuthInterceptor
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.annotation.JsonSetter
import com.fasterxml.jackson.annotation.Nulls
import com.fasterxml.jackson.databind.ObjectMapper
import com.fasterxml.jackson.databind.SerializationFeature
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer
import com.fasterxml.jackson.module.kotlin.KotlinFeature
import com.fasterxml.jackson.module.kotlin.kotlinModule
import jakarta.annotation.Resource
import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import org.springframework.core.Ordered
import org.springframework.core.annotation.Order
import org.springframework.http.converter.HttpMessageConverter
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
import org.springframework.web.cors.CorsConfiguration
import org.springframework.web.cors.UrlBasedCorsConfigurationSource
import org.springframework.web.filter.CorsFilter
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer
import java.time.LocalDate
import java.time.LocalDateTime
import java.time.LocalTime
import java.time.format.DateTimeFormatter


/**
 * WebConfig
 *
 * @author cc
 * @version 1.0
 * @since 2023/9/15
 */
@Configuration
class WebConfig(private val authInterceptor: AuthInterceptor) : WebMvcConfigurer {

    @Resource
    private lateinit var objectMapper: ObjectMapper

//    override fun addInterceptors(registry: InterceptorRegistry) {
//        registry.addInterceptor(authInterceptor).addPathPatterns("/**").excludePathPatterns("/login")
//    }

    @Bean
    fun corsFilter(): CorsFilter {
        val source = UrlBasedCorsConfigurationSource()
        val corsConfiguration = CorsConfiguration()
        corsConfiguration.allowCredentials = true
        corsConfiguration.addAllowedHeader("*")
        corsConfiguration.addAllowedOriginPattern("*")
        corsConfiguration.addAllowedMethod("*")
        source.registerCorsConfiguration("/**", corsConfiguration)
        return CorsFilter(source)
    }

    override fun extendMessageConverters(converters: MutableList<HttpMessageConverter<*>>) {
        objectMapper.setDefaultSetterInfo(JsonSetter.Value.forValueNulls(Nulls.SKIP))
        converters.removeIf { converter -> converter is MappingJackson2HttpMessageConverter }
        converters.add(0, MappingJackson2HttpMessageConverter(objectMapper))
    }

    @Bean
    @Order(Ordered.HIGHEST_PRECEDENCE)
    fun customJackson(): Jackson2ObjectMapperBuilderCustomizer {
        return Jackson2ObjectMapperBuilderCustomizer {
            it.apply {
                serializerByType(
                    LocalDateTime::class.java, LocalDateTimeSerializer(
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
                    )
                )
                serializerByType(
                    LocalDate::class.java, LocalDateSerializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                )
                serializerByType(
                    LocalTime::class.java, LocalTimeSerializer(DateTimeFormatter.ofPattern("HH:mm:ss"))
                )
                serializerByType(Long::class.java, ToStringSerializer.instance).serializerByType(java.lang.Long.TYPE, ToStringSerializer.instance)
                deserializerByType(
                    LocalDateTime::class.java, LocalDateTimeDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))
                )
                deserializerByType(
                    LocalDate::class.java, LocalDateDeserializer(DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                )
                deserializerByType(
                    LocalTime::class.java, LocalTimeDeserializer(DateTimeFormatter.ofPattern("HH:mm:ss"))
                )
                serializationInclusion(JsonInclude.Include.NON_NULL)
                failOnUnknownProperties(false)
                failOnEmptyBeans(false)
                featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
                modules(kotlinModule {
                    configure(KotlinFeature.NullIsSameAsDefault, true)
                    enable(KotlinFeature.NullToEmptyCollection)
                }, JavaTimeModule())
            }
        }
    }
}


/*fun main() {
    val objectMapper = ObjectMapper().apply {
        registerModules(
            KotlinModule.Builder().configure(KotlinFeature.NullIsSameAsDefault, true).build(), JavaTimeModule()

        )
    }

    val json = """
    {
        "orderNo": null,
        "carNo": "123",
        "parkingLotId": 68,
        "parkingSpaceNo": "abc",
        "inDeviceNo": "abc",
        "inName": "带我始群",
        "inImg": "http://dummyimage.com/400x400",
        "outDeviceNo": "abc",
        "outName": "达无地又设意此",
        "outImg": "http://dummyimage.com/400x400",
        "parkingFee": 18,
        "parkingTime": 46063734611,
        "parkingStatus": 35,
        "payMethod": 39,
        "tollman": "abc",
        "orderStatus": 87
    }
    """.trimIndent()
    println(objectMapper.readValue<ParkingOrder>(json))
}*/
